#! /usr/bin/python
#-*- coding: UTF-8 -*-

import socket, select
import logging

EOL1 = b'\n\n'
EOL2 = b'\n\r\n'
response  = b'HTTP/1.0 200 OK\r\nDate: Mon, 1 Jan 1996 01:01:01 GMT\r\n'
response += b'Content-Type: text/plain\r\nContent-Length: 13\r\n\r\n'
response += b'Hello, world!'

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(("0.0.0.0", 8080))
s.listen(100)
#set to non-blocking
s.setblocking(0)

epoll = select.epoll()
epoll.register(s.fileno(), select.EPOLLIN)

try:
    clients = {}; requests = {}; responses = {}
    while 1:
        events = epoll.poll(10)
        if len(events)==0:
            print("time out")
            continue
        for fileno, event in events:
            if fileno == s.fileno():
                client, address = s.accept()
                client.setblocking(0)
                epoll.register(client, select.EPOLLIN)
                clients[client.fileno()] = client
                requests[client.fileno()] = b''
                responses[client.fileno()] = response
            elif event & select.EPOLLIN:
                requests[fileno] += clients[fileno].recv(4096)
                if EOL1 in requests[fileno] or EOL2 in requests[fileno]:
                    epoll.modify(fileno, select.EPOLLOUT)
                    print('-'*40+'\n'+requests[fileno].decode()[:-2])
            elif event & select.EPOLLOUT:
                byteswritten = clients[fileno].send(responses[fileno])
                responses[fileno] = responses[fileno][byteswritten:]
                if len(response[fileno])==0:
                    epoll.modify(fileno, 0)
                    clients[fileno].shutdown(socket.SHUT_REWR)
            elif event & select.EPOLLHUP:
                epoll.unregister(fileno)
                clients[fileno].close()
                del clients[fileno]
finally:
    epoll.unregister(s.fileno())
    epoll.close()
    s.close()

#酣畅淋漓，一气呵成
